<!--
 * @Author: PoJun
 * @Date: 2024-06-20 19:04:02
 * @LastEditors: PoJun
 * @LastEditTime: 2024-06-25 16:14:27
 * @Message: Nothing
-->
<template>
  <view class="barrage" :style="[vuex_theme]">
    <!-- 内容区域放前面, 避免在切换时导致的莫名其妙的动画重置 -->
    <view class="barrage-content" :style="[getContentBg]" @tap="fullScreen = !fullScreen">
      <view class="barrage-content-box" :style="[getBarrageStyle]">
        <view
          id="barrageText"
          class="barrage-content-text"
          :class="[config.isScroll ? 'barrage-content-scroll' : '']"
          :style="[getAnimateStyle]"
        >
          {{ config.barrageText }}
        </view>
      </view>
    </view>
    <!-- 头部,不做防护, 反正要全屏的 -->
    <uv-navbar
      title="弹幕发射器"
      @leftClick="customNavbarBack"
      v-if="!fullScreen"
      titleWidth="auto"
    ></uv-navbar>
    <!-- 按钮区域 -->
    <view class="barrage-footer" v-if="!fullScreen">
      <uv-icon
        name="question-circle"
        size="26"
        hoverClass="uv-hover-class"
        @click="dispatchToast"
      ></uv-icon>

      <view class="barrage-footer-input">
        <uv-input
          placeholder="请输入内容"
          border="surround"
          v-model="config.barrageText"
        ></uv-input>
      </view>

      <uv-icon
        name="setting-fill"
        size="28"
        hoverClass="uv-hover-class"
        @click="openSetting"
      ></uv-icon>
    </view>
    <!-- 配置弹窗 -->
    <uv-popup ref="settingsDialog" mode="bottom" :overlayStyle="{ backgroundColor: 'transparent' }">
      <uv-toolbar
        cancelText=" "
        :confirmColor="vuex_theme['--theme-primary-color']"
        @confirm="$refs.settingsDialog.close()"
      ></uv-toolbar>
      <view class="barrage-settings">
        <uv-form labelPosition="left" :model="config" :borderBottom="false" labelWidth="auto">
          <uv-form-item label="滚动弹幕：" :borderBottom="false">
            <view class="uv-m-l-14">
              <uv-switch
                :activeColor="vuex_theme['--theme-primary-color']"
                v-model="config.isScroll"
                size="20"
              ></uv-switch>
            </view>
          </uv-form-item>
          <uv-form-item label="文字样式：" :borderBottom="false">
            <uv-checkbox-group v-model="config.effect" placement="row">
              <uv-checkbox
                :activeColor="vuex_theme['--theme-primary-color']"
                name="bold"
                label="加粗"
                :customStyle="{ padding: '8px' }"
              ></uv-checkbox>
              <uv-checkbox
                :activeColor="vuex_theme['--theme-primary-color']"
                name="shadow"
                label="阴影"
                :customStyle="{ padding: '8px' }"
              ></uv-checkbox>
            </uv-checkbox-group>
          </uv-form-item>
          <uv-form-item label="滚动速度：" :borderBottom="false">
            <uv-slider
              v-model="config.aniSpeed"
              :customStyle="{ flex: 1 }"
              show-value
              :min="1"
              :max="10"
              :activeColor="vuex_theme['--theme-primary-color']"
            ></uv-slider>
          </uv-form-item>
          <uv-form-item label="文字大小：" :borderBottom="false">
            <uv-slider
              v-model="config.fontSize"
              :customStyle="{ flex: 1 }"
              show-value
              :min="1"
              :max="50"
              :activeColor="vuex_theme['--theme-primary-color']"
            ></uv-slider>
          </uv-form-item>
          <uv-form-item label="文字间距：" :borderBottom="false">
            <uv-slider
              v-model="config.letterSpace"
              :customStyle="{ flex: 1 }"
              show-value
              :min="0"
              :max="25"
              :activeColor="vuex_theme['--theme-primary-color']"
            ></uv-slider>
          </uv-form-item>
          <uv-form-item label="文字颜色：" :borderBottom="false">
            <view
              class="barrage-settings--color"
              @tap="openPickColor('textColor')"
              hover-class="uv-hover-class"
              :style="{ backgroundColor: config.textColor }"
            ></view>
          </uv-form-item>
          <uv-form-item label="背景颜色：" :borderBottom="false">
            <view
              class="barrage-settings--color"
              @tap="openPickColor('bgColor')"
              hover-class="uv-hover-class"
              :style="{ backgroundColor: config.bgColor }"
            ></view>
          </uv-form-item>
        </uv-form>
      </view>
    </uv-popup>
    <!-- 颜色选择器 -->
    <uv-pick-color
      ref="pickerColor"
      :color="{ r: 0, g: 0, b: 0, a: 1 }"
      @confirm="confirm"
    ></uv-pick-color>
  </view>
</template>

<script>
import commonFuncMixin from "@/utils/commonFuncMixin.js"
export default {
  mixins: [commonFuncMixin],
  data() {
    return {
      fullScreen: false, // 是否全屏展示
      config: {
        barrageText: "体验弹幕",
        effect: ["bold"],

        bgColor: "#000000", // 容器背景色
        isScroll: true, // 文字是否开启滚动

        textColor: "#FFFFFF", // 文字颜色
        fontSize: 10, // 文字大小
        letterSpace: 3, // 文字间距
        aniSpeed: 5 // 滚动速度
      },

      currentOpenType: "",
      containerHeight: 800 // 给个默认值吧
    }
  },
  methods: {
    openSetting() {
      this.$refs.settingsDialog.open()
    },
    openPickColor(type) {
      this.currentOpenType = type
      this.$refs.pickerColor.open()
    },
    confirm({ hex }) {
      this.config[this.currentOpenType] = hex
    },
    dispatchToast() {
      uni.showModal({
        title: "提示",
        content: "点击屏幕可进入全屏模式, 再次点击退出。右侧设置按钮可配置弹幕样式。",
        showCancel: false
      })
    },
    computeContainer() {
      // 由于动画的旋转, 这里获取的高度其实是宽度
      this.$nextTick(() => {
        const view = uni.createSelectorQuery().in(this).select("#barrageText")
        view
          .boundingClientRect(data => {
            this.containerHeight = data.height
          })
          .exec()
      })
    }
  },
  computed: {
    // 永远会有值,不需要担心默认值
    getContentBg() {
      return { backgroundColor: this.config.bgColor }
    },
    // 字体相关的值乘以固定的倍数, 用户拖的方便
    getBarrageStyle() {
      return {
        color: this.config.textColor,
        fontSize: this.config.fontSize * 10 + "px",
        letterSpacing: this.config.letterSpace * 10 + "px",
        fontWeight: this.config.effect.includes("bold") ? "bold" : "normal",
        textShadow: this.config.effect.includes("shadow") ? `0 0 24px ${this.config.textColor}` : ""
      }
    },
    getAnimateStyle() {
      return {
        "animation-duration": `${this.containerHeight / 50 / this.config.aniSpeed}s`
      }
    }
  },
  watch: {
    config: {
      deep: true,
      immediate: true,
      handler: function () {
        this.computeContainer()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.barrage {
  height: 100vh;
  &-content {
    width: 100vw;
    height: 100vh;

    &-box {
      min-width: 100vh;
      height: 100vw;
      display: flex;
      justify-content: center;
      align-items: center;
      transform-origin: 50vw 50vw;
      transform: rotate(90deg);
      white-space: nowrap;
      overflow: hidden;
      text-align: center;
      // animation: textShake 0.5s linear infinite;
    }
    &-text {
      min-width: 100vh;
    }
    &-scroll {
      animation: textScroll 5s linear infinite;
      animation-fill-mode: forwards;
    }
    @keyframes textScroll {
      0% {
        transform: translateX(100%);
      }
      100% {
        transform: translateX(-100%);
      }
    }
  }
  &-footer {
    position: fixed;
    left: 0;
    bottom: 0;
    padding: 10px 25rpx;
    padding-bottom: calc(10px + constant(safe-area-inset-bottom));
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: row;
    background-color: #fff;
    z-index: 22;
    width: 100vw;
    box-sizing: border-box;
    &-input {
      flex: 1;
      padding: 0 20rpx;
    }
  }
  &-settings {
    padding: 0 36rpx;
    &--color {
      width: 40px;
      height: 40px;
      border-radius: 4px;
      box-shadow: 0 0px 8px 1px rgba(0, 0, 0, 0.1);
    }
  }
}
</style>
